import React from 'react'
import style from './style'
import Link from '../link'
import Button from '../button'
import IconFont from '../iconFont'
import mime from 'mime-types'
import cx from 'classnames'
import util from '../../util'
import { Loading } from '../loading'
import {FieldContainer, FieldBox} from '../form'

// 20MB
const MAX_SIZE_IMAGE = 20971520

export default
class FileUpload extends React.Component {

	init = { 
    img: false,
    imgDataUrl: '',
    file: null,
    files: [],
    uploaded: []
	}

  files = []
  uploaded = []

  constructor(props) {
    super(props)
    const { file } = props
    this.state = {
      ...this.init,
      img: !!file,
      imgDataUrl: file || ''
    }
  }

  componentWillReceiveProps(props) {
    if (!this.props.file && props.file) {
      this.setState({
        ...this.init,
        img: true,
        imgDataUrl: props.file
      })
    }
  }

  static defaultProps = {
    size: 36,
    margin: 5,
    row: 6,
    valueRender: ()=>{}
  }

  static propsType = {
    onChange: React.PropTypes.func,
    onUpload: React.PropTypes.func
  }

	reset() {
    this.files = []
    this.uploaded = []
		this.setState({
			...this.state,
			...this.init
		})
	}

	upload() {
		this.refs.file.click()
	}

  handleClick() {
		this.upload()
  }

  handleRemove({ id }) {
		const uploaded = (this.uploaded || []).filter(f => f.id !== id)
		const files = (this.files || []).filter(f => f.id !== id) 

    this.uploaded = uploaded
    this.files = files

		//if (uploaded.length == files.length) {
		this.props.onUpload(uploaded)
		//}

    this.setState({
      files,
      uploaded
    })
  }

  handleFileChange() {
    const files = this.refs.file.files
    const maxSize = this.props.fileSize || MAX_SIZE_IMAGE/1024;
    const sizeText = (maxSize/1024).toFixed(2);
    function next(i) {
      const file = files[i]
      if (!file) {
        // clear
        this.refs.file.value = ''
        return
      }
      if (this.props.accept === 'image/*') {
        if (file.type.indexOf('image') !== 0) {
          this.refs.file.value = ''
          alert('只能上传图片!')
          return
        }

      }
      if (file.size > maxSize*1024) {
        this.refs.file.value = ''
        alert(`图片最大不能超过${sizeText}MB!`)
        return
      }
      const reader = new FileReader()
      reader.onload = e => this.handleFileLoaded(e, file)
      reader.readAsDataURL(file);
      next.call(this, i+1)
    }

    next.call(this, 0)
  }

  handleFileLoaded(e, _file) {

    const dataURL = e.target.result;
    const mimeType = _file.type || dataURL.split(",")[0].split(":")[1].split(";")[0];

    const file = {
      // 文件大小
      size: e.total,
      // 文件类型
      type: mimeType,
      name: _file.name,
      file: _file,
			dataURL
    }

    if (!this.props.multi) {
      this.props.onChange(file)
      if (mimeType.indexOf('image') === 0 || this.props.img) {
        this.setState({
          img: true,
          imgDataUrl: dataURL,
          file
        })
      } else {
        this.setState({
          img: false,
          imgDataUrl: '',
          file
        })
      }
    } else {
      const files = (mimeType.indexOf('image') === 0 || this.props.img)? [
        ...(this.files || []),
        {
          img: true,
          imgDataUrl: dataURL,
          file,
          id: Symbol(file.name)
        }
      ]: [
        ...(this.files || []),
        {
          img: false,
          imgDataUrl: '',
          file,
          id: Symbol(file.name)
        }
      ]

      this.files = files

      this.props.onChange(util.last(files), data => {

        if (this.files.some(f => f.id === data.id)) {
          let uploaded = [
            ...this.uploaded,
            data
          ]
          this.uploaded = uploaded
        }

        this.props.onUpload(this.uploaded)

        this.setState({
          uploaded: this.uploaded
        })
      }, this.files)

      this.setState({
        files
      })
    }
  }

  render() {
    const { 
      className, 
      label, 
      button,
      buttonText = '上传文件', 
      link, 
      multi, 
      size,
      required,
      value = [],
      name,
      imageStyle={},
      valueRender,
      placeholder,
    } = this.props;
    let render;
    const vRender = valueRender(value);
    if (link) {
      render = (
        <Link
          className={cx({
            [style.root]: true,
            [className]: className
          })}
          onClick={::this.handleClick}
        >
          <span>{ placeholder }</span>
          <input 
            accept={this.props.accept || '*'}
            onChange={::this.handleFileChange}
            type="file" 
            ref="file"/>
        </Link>
      )
    } else if (button) {
      render = (
       <div className={cx({
         [style.root]: true,
         [className]: className
       })}>
         <Button 
           { ...(typeof button == 'string'? { [button]: true }: {}) }
           onClick={::this.handleClick} 
           label={buttonText}
         />
          <input 
            accept={this.props.accept || '*'}
            onChange={::this.handleFileChange}
            type="file" 
            ref="file"/>
          {vRender}
        </div>
      )
    } else if (multi) {
      const { 
        className, 
        max, 
        size, 
        row, 
        ratio
      } = this.props
      let files = [
        ...this.state.files,
        'add'
      ]
			//if (files.length > max) files.pop()
			let width=size, height=size
			if (ratio) {
				height = width/ratio
			}
      render = (
				<div 
					className={cx({
						[className]: className,
						[style.root]: true,
						[style.multi]: true,
						[style.empty]: !this.state.files.length
        })}>
					{
						label?
						<div>{ label }</div>
						: null
					}
          <ul style={{
            maxWidth: `${ size* row+ this.props.margin*(row-1) }px`
          }}>
            {
              files.map((v, i) => {
                const marginLeft = (i == 0 || i%row == 0) ? 0: this.props.margin
                const marginTop = i>row-1? this.props.margin: 0
                if (v === 'add') {
                  return (
                    <li 
                      key={i}
                      style={{
                        width: `${width}px`,
                        height: `${height}px`,
                        marginLeft: `${marginLeft}px`,
                        marginTop: `${marginTop}px`,
                        position: 'relative',
                      }}
                      className={style.add}
                      onClick={::this.handleClick}
                    >
                      <div style={{
                        width: '17px',
                        height: '17px',
                        position: 'absolute',
                        top: '50%',left: '50%',margin: '-8px 0 0 -8px',
                      }}>
                        <div style={{
                          width: '100%',
                          height: '50%',
                          position: 'absolute',
                          top: '0',left: '0',
                          borderBottom: '1px solid #aaa'
                        }}></div>
                        <div style={{
                          width: '50%',
                          height: '100%',
                          position: 'absolute',
                          top: '0',left: '0',
                          borderRight: '1px solid #aaa'
                        }}></div>
                      </div>
                    </li>
                  )
                } else if (v.img) {
                  const isDone = this.state.uploaded.some(obj => obj.id == v.id)
                  return (
                    <li 
                      className={style['add-img']}
                      key={i} 
                      style={{ 
                        backgroundImage: `url(${v.imgDataUrl})` ,
                        width: `${width}px`,
                        height: `${height}px`,
                        marginLeft: `${marginLeft}px`,
                        marginTop: `${marginTop}px`
                      }}
                    >
                      {
                        isDone? null: <Loading height="4" className={style.loading} loading/>
                      }
                      {
                        isDone? null: <span className={style.cover}/>
                      }
                      {
                        isDone? <IconFont value='tick' className={style['add-img-tick']}/>: null
                      }
                      <span 
                        className={style['add-img-edit-cover']}>
                        <Link 
                          icon="close" 
                          onClick={() => this.handleRemove(v)}
                          className={style['add-img-close']}/>
                      </span>
                    </li>
                  )
                } else {
                  return (
                    <li 
                      style={{
                        width: `${size}px`,
                        height: `${size}px`
                      }}
                      key={i}
                    >{ v.name }</li>
                  )
                }
              })
            }
          </ul>
          <input 
            multiple
            accept={this.props.accept || '*'}
            onChange={::this.handleFileChange}
            type="file" 
            ref="file"/>
        </div>
      )
    }else {
      render = <Link 
        className={cx({
          [style.root]: true,
          [style.single]:true,
          [style.fillImage]: this.state.img,
          [className]: className
        })}
        onClick={::this.handleClick}
      >
        {
          this.state.img?
          <i 
            className={style.img} 
            style={
              { 
                backgroundImage: `url(${this.state.imgDataUrl})` ,
                ...imageStyle
              }
            }/>: null
        }
        {
          (!this.state.img && this.state.file)? (
            <span>{ this.state.file.name }</span>
          ): (
            <span>{ this.props.imageLabel }</span>
          )
        }
        <input 
          accept={this.props.accept || '*'}
          onChange={::this.handleFileChange}
          type="file" 
          ref="file"
        />
      </Link>
    }
   
    return (
      <FieldBox
        label={label}
        name={name}
        required={required}
      >
        {render}
      </FieldBox>
    )
  }
}
